﻿#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;

/*
模板概论：
	C++提供了函数模板（function template），所谓函数模板，实际上是建立一个通用函数，其函数类型和形参不具体指定，用一个虚拟的类型
	来代表，这个通用函数就称为函数模板。凡事函数体相同的函数都可以使用这个模板代替，不必定义多个函数，只需在模板中定义一次即可。
	在调用函数时系统会根据实参的类型来取代模板中的虚拟类型，从而实现不同函数的功能。
C++中提供两种模板机制：函数模板和类模板。
类属 - 类型参数化，又称参数模板。

总结：
	模板把函数或类要处理的数据类型参数化，表现为参数的多态性，称为类属。
	模板用于表达逻辑结构相同，但具体数据元素类型不同的数据对象的通用行为。

函数模板的原理：
	函数模板声明处进行编译，调用时，进行二次编译。

函数模板的局限性：
	传的参数如果是结构体类型或数组类型，若比较大小，就比较不了了。
*/

void mySwapInt(int &a, int &b) {
	int temp = a;
	a = b;
	b = temp;
}

void mySwapDouble(double &a, double &b) {
	double temp = a;
	a = b;
	b = temp;
}

// 定义一个函数模板 
// 定义一个泛型，取名T 
template <class T> void mySwap(T &a, T &b) {
	T temp = a;
	a = b;
	b = temp;
}

template <class T>
void mySwap2() {

}

template <class T>
T add(T a, T b) {
	return a + b; 
}

void test01() {
	int a = 10;
	int b = 20;
	// 调用函数模板
	// 1. 编译器会根据实际参数自动推倒类型 
	mySwap(a, b); 
	cout << a << b << endl; 
	char c = 'k';
	// mySwap(a, c);  // 报错，a和c的类型不同，编译器没法推导 
	// 2. 显式指定类型 
	mySwap<int>(a, b);
	// mySwap<double>(a, b); // 引用类型没有隐式类型转换  
	// 没有参数的函数模板，不能自动推导类型，需要显式指定类型，否则会报错 
	mySwap2<float>();
	// 显式指定类型，实参可以隐式类型转换，但注意，隐式类型转换只能从小范围转为大范围 
	float d = 10.8;
	double e = 15.6;
	int c = add<double>(d, e); 
}

int main()
{

	test01(); 

	system("pause");
	return EXIT_SUCCESS;
}
